package data

import (
	//"database/sql/driver"
	"encoding/json"
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"time"
)

type TimeUtil struct{}

func (tu *TimeUtil) ToStr() string {
	const shortForm = "2006-01-01 15:04:05"
	t := time.Now()
	temp := time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), time.Local)
	str := temp.Format(shortForm)

	return str
}

//自定义时间类型
type LocalTime time.Time

//重写MarshalJSON方法来实现gorm查询时间字段事数据解析
func (t *LocalTime) MarshalJSON() ([]byte, error) {
	tTime := time.Time(*t)
	return []byte(fmt.Sprintf("\"%v\"", tTime.Format("2006-01-02 15:04:05"))), nil
}

//取当前时间
func (t LocalTime) Now() *LocalTime {
	var result LocalTime

	ti := time.Now()
	str, err := json.Marshal(ti)
	if err != nil {
		return &result
	}

	json.Unmarshal([]byte(str), &result)

	return &result
}

// //在存储时调⽤
// func (t LocalTime) Value() (driver.Value, error) {
// 	var zeroTime time.Time
// 	tlt := time.Time(t)
// 	//判断给定时间是否和默认零时间的时间戳相同
// 	if tlt.UnixNano() == zeroTime.UnixNano() {
// 		return nil, nil
// 	}
// 	return tlt, nil
// }

//在数据查询出来之前对数据进⾏相关操作
func (t *LocalTime) Scan(v interface{}) error {
	if value, ok := v.(time.Time); ok {
		*t = LocalTime(value)
		return nil
	}
	return fmt.Errorf("can not convert %v to timestamp", v)
}

//取当前时间
func (this TimeUtil) Current(formatStr ...string) string {
	date := time.Now()
	if len(formatStr) < 1 {
		return date.Format("2006-01-02 15:04:05")
	}

	return this.Format(date, formatStr[0])
}

//取今天日期
func (this TimeUtil) Today(formatStr ...string) string {
	date := time.Now()
	if len(formatStr) < 1 {
		return date.Format("2006-01-02")
	}

	return this.Format(date, formatStr[0])
}

//取今天开始时间
func (this TimeUtil) TodaySt() string {
	return time.Now().Format("2006-01-02") + "00:00:00"
}

//取今天结束时间
func (this TimeUtil) TodayEd() string {
	return time.Now().Format("2006-01-02") + "23:59:59"
}

//判断字符串是否是日期型
func (this TimeUtil) IsTime(str string) bool {
	local, _ := time.LoadLocation("Asia/Shanghai")
	if len(str) == 19 {
		_, err := time.ParseInLocation("2006-01-02 15:04:05", str, local)
		return err == nil
	}

	if len(str) == 16 {
		_, err := time.ParseInLocation("2006-01-02 15:04", str, local)
		return err == nil
	}

	_, err := time.ParseInLocation("2006-01-02", str, local)
	return err == nil
}

//时间格式化
func (this TimeUtil) Format(date time.Time, formatStr string) string {
	formatStr = strings.ToUpper(formatStr)
	switch formatStr {
	case "YYYY/MM/DD HH:MM:SS":
		return date.Format("2006/01/02 15:04:05")
	case "YYYY/MM/DD":
		return date.Format("2006/01/02")
	case "MM/DD/YYYY HH:MM:SS":
		return date.Format("01/02/2006 15:04:05")
	case "MM-DD-YYYY HH:MM:SS":
		return date.Format("01-02-2006 15:04:05")
	case "YYYY-MM-DD HH:MM:SS":
		return date.Format("2006-01-02 15:04:05")
	case "YYYY-MM-DD HH:MM":
		return date.Format("2006-01-02 15:04")
	case "YYYY-MM-DD HH":
		return date.Format("2006-01-02 15")
	case "YYYY-MM-DD":
		return date.Format("2006-01-02")
	case "YYYY-MM":
		return date.Format("2006-01")
	case "YYYY":
		return date.Format("2006")
	case "HH:MM:SS":
		return date.Format("15:04:05")
	case "HH:MM":
		return date.Format("15:04")
	case "HH":
		return date.Format("15")
	case "YYYY年MM月DD日 HH:MM:SS":
		return date.Format("2006年01月02日 15:04:05")
	case "YYYY年MM月DD日 HH:MM":
		return date.Format("2006年01月02日 15:04")
	case "YYYY年MM月DD日 HH":
		return date.Format("2006年01月02日 15")
	case "YYYY年MM月DD日":
		return date.Format("2006年01月02日")
	case "YYYY年MM月":
		return date.Format("2006-01")
	case "YYYY-MM-DD HH:MM:00":
		return date.Format("2006-01-02 15:04") + ":00"
	case "YYYY-MM-DD HH:00:00":
		return date.Format("2006-01-02 15") + ":00:00"
	case "YYYY-MM-DD 00:00:00":
		return date.Format("2006-01-02") + " 00:00:00"
	default:
		return date.Format("2006-01-02 15:04:05")
	}
}

//字符串转时间
func (this TimeUtil) ToDate(str string) time.Time {
	str = strings.TrimSpace(str)
	if "" == str {
		return time.Now()
	}

	str = strings.Replace(str, "/", "-", -1)
	str = strings.Replace(str, "T", " ", -1)
	str = strings.Replace(str, "Z", "", -1)
	str = strings.Replace(str, "z", "", -1)

	iEd := strings.LastIndex(str, ".")
	if iEd > -1 {
		str = str[:iEd]
	}

	local, _ := time.LoadLocation("Asia/Shanghai")
	if len(str) == 19 {
		result, _ := time.ParseInLocation("2006-01-02 15:04:05", str, local)
		return result
	}

	if len(str) == 16 {
		result, _ := time.ParseInLocation("2006-01-02 15:04", str, local)
		return result
	}

	result, _ := time.ParseInLocation("2006-01-02", str, local)
	return result
}

/**
* 获取指定天数后的时间
* @param date 起始时间
* @param iCount 天数
* @return
 */
func (this TimeUtil) AddDay(date time.Time, iCount int) time.Time {
	if 0 == iCount {
		return date
	}

	d, _ := time.ParseDuration(strconv.Itoa(iCount*24) + "h")
	result := date.Add(d)

	return result
}

/**
* 获取指定小时后的时间
* @param date 起始时间
* @param iCount 小时数
* @return
 */
func (this TimeUtil) AddHour(date time.Time, iCount int) time.Time {
	if 0 == iCount {
		return date
	}

	d, _ := time.ParseDuration(strconv.Itoa(iCount) + "h")
	result := date.Add(d)

	return result
}

/**
* 获取指定分钟后的时间
* @param date 起始时间
* @param iCount 分数
* @return
 */
func (this TimeUtil) AddMinute(date time.Time, iCount int) time.Time {
	if 0 == iCount {
		return date
	}

	d, _ := time.ParseDuration(strconv.Itoa(iCount) + "m")
	result := date.Add(d)

	return result
}

/**
* 获取指定月后的时间
* @param date 起始时间
* @param iCount 月数
* @return
 */
func (this TimeUtil) AddMonth(date time.Time, iCount int) time.Time {
	if 0 == iCount {
		return date
	}

	return date.AddDate(0, iCount, 0)
}

/**
* 获取指定年后的时间
* @param date 起始时间
* @param iCount 年数
* @return
 */
func (this TimeUtil) AddYear(date time.Time, iCount int) time.Time {
	if 0 == iCount {
		return date
	}

	return date.AddDate(iCount, 0, 0)
}

/**
* 获取指定分钟后的时间
* @param date 起始时间
* @param iT 时间参数,分别是年、月、日、时、分、秒
* @return
 */
func (this TimeUtil) Add(date time.Time, iT ...int) time.Time {
	if len(iT) < 1 {
		return date
	}

	if len(iT) == 1 {
		return date.AddDate(iT[0], 0, 0)
	}

	if len(iT) == 2 {
		return date.AddDate(iT[0], iT[1], 0)
	}

	if len(iT) == 3 {
		return date.AddDate(iT[0], iT[1], iT[2])
	}

	result := date.AddDate(iT[0], iT[1], iT[2])
	d, _ := time.ParseDuration(strconv.Itoa(iT[3]) + "h")
	result = result.Add(d)

	if len(iT) == 4 {
		return result
	}

	d, _ = time.ParseDuration(strconv.Itoa(iT[4]) + "m")
	result = result.Add(d)

	if len(iT) == 5 {
		return result
	}

	d, _ = time.ParseDuration(strconv.Itoa(iT[5]) + "s")
	result = result.Add(d)

	return result
}

// 计算日期相差多少分钟(注意:3到6差距是3而不是4)
func (this TimeUtil) gapMinute(t1, t2 string) (hour int) {
	local, _ := time.LoadLocation("Asia/Shanghai")

	dStDate, _ := time.ParseInLocation("2006-01-02 15:04:05", string(t1[:16])+":00", local)
	dEdDate, _ := time.ParseInLocation("2006-01-02 15:04:05", string(t2[:16])+":00", local)

	hour = int(dStDate.Sub(dEdDate).Minutes())
	if hour < 0 {
		hour = -hour
	}

	return
}

// 计算日期相差多少分钟(注意:3到6差距是3而不是4)
func (this TimeUtil) GapMinute(t1, t2 interface{}) (hour int) {
	if reflect.TypeOf(t1).Name() == "string" {
		return this.gapMinute(t1.(string), t2.(string))
	}

	if reflect.TypeOf(t1).Name() == "Time" {
		d1 := t1.(time.Time).Format("2006-01-02 15:04:00")
		d2 := t2.(time.Time).Format("2006-01-02 15:04:00")
		return this.gapMinute(d1, d2)
	}

	if reflect.TypeOf(t1).Name() == "time.Time" {
		d1 := t1.(time.Time).Format("2006-01-02 15:04:00")
		d2 := t2.(time.Time).Format("2006-01-02 15:04:00")
		return this.gapMinute(d1, d2)
	}

	return -1
}

// 计算日期相差多少小时(注意:3到6差距是3而不是4)
func (this TimeUtil) gapHour(t1, t2 string) (hour int) {
	local, _ := time.LoadLocation("Asia/Shanghai")

	dStDate, _ := time.ParseInLocation("2006-01-02 15:04:05", string(t1[:14])+"00:00", local)
	dEdDate, _ := time.ParseInLocation("2006-01-02 15:04:05", string(t2[:14])+"00:00", local)

	hour = int(dStDate.Sub(dEdDate).Hours())
	if hour < 0 {
		hour = -hour
	}

	return
}

// 计算日期相差多少小时(注意:3到6差距是3而不是4)
func (this TimeUtil) GapHour(t1, t2 interface{}) (hour int) {
	if reflect.TypeOf(t1).Name() == "string" {
		return this.gapHour(t1.(string), t2.(string))
	}

	if reflect.TypeOf(t1).Name() == "Time" {
		d1 := t1.(time.Time).Format("2006-01-02 15:00:00")
		d2 := t2.(time.Time).Format("2006-01-02 15:00:00")
		return this.gapHour(d1, d2)
	}

	if reflect.TypeOf(t1).Name() == "time.Time" {
		d1 := t1.(time.Time).Format("2006-01-02 15:00:00")
		d2 := t2.(time.Time).Format("2006-01-02 15:00:00")
		return this.gapHour(d1, d2)
	}

	return -1
}

// 计算日期相差多少天(注意:3到6差距是3而不是4)
func (this TimeUtil) GapDay(t1, t2 interface{}) (day int) {
	if reflect.TypeOf(t1).Name() == "string" {
		return this.gapDay(t1.(string), t2.(string))
	}

	if reflect.TypeOf(t1).Name() == "Time" {
		d1 := t1.(time.Time).Format("2006-01-02 00:00:00")
		d2 := t2.(time.Time).Format("2006-01-02 00:00:00")
		return this.gapDay(d1, d2)
	}

	if reflect.TypeOf(t1).Name() == "time.Time" {
		d1 := t1.(time.Time).Format("2006-01-02 00:00:00")
		d2 := t2.(time.Time).Format("2006-01-02 00:00:00")
		return this.gapDay(d1, d2)
	}

	return -1
}

// 计算日期相差多少天(注意:3到6差距是3而不是4)
func (this TimeUtil) gapDay(t1, t2 string) (day int) {
	local, _ := time.LoadLocation("Asia/Shanghai")

	dStDate, _ := time.ParseInLocation("2006-01-02 15:04:05", string(t1[:10])+" 00:00:00", local)
	dEdDate, _ := time.ParseInLocation("2006-01-02 15:04:05", string(t2[:10])+" 00:00:00", local)

	day = int(dStDate.Sub(dEdDate).Hours() / 24)
	if day < 0 {
		day = -day
	}

	//如果时间差距不够24小时,但是已经跨天,则时间应该加1
	if (dStDate.Format("2006-01-02") != dEdDate.Format("2006-01-02")) && (day == 0) {
		day = 1
	}

	return
}

// 计算日期相差多少月(注意:3到6差距是3而不是4)
func (this TimeUtil) GapMonth(t1, t2 interface{}) (month int) {
	if reflect.TypeOf(t1).Name() == "string" {
		d1, _ := time.Parse("2006-01-02 15:04:05", t1.(string))
		d2, _ := time.Parse("2006-01-02 15:04:05", t2.(string))
		return this.gapMonth(d1, d2)
	}

	if reflect.TypeOf(t1).Name() == "Time" {
		return this.gapMonth(t1.(time.Time), t2.(time.Time))
	}

	if reflect.TypeOf(t1).Name() == "time.Time" {
		return this.gapMonth(t1.(time.Time), t2.(time.Time))
	}

	return -1
}

// 计算日期相差多少月(注意:3到6差距是3而不是4)
func (this TimeUtil) gapMonth(t1, t2 time.Time) (month int) {
	m1 := (t1.Year() * 12) + int(t1.Month())
	m2 := (t2.Year() * 12) + int(t2.Month())

	month = m2 - m1

	if month < 0 {
		month = -month
	}

	return
}

// 计算日期相差多少年(注意:3到6差距是3而不是4)
func (this TimeUtil) GapYear(t1, t2 interface{}) (year int) {
	if reflect.TypeOf(t1).Name() == "string" {
		d1, _ := time.Parse("2006-01-02 15:04:05", t1.(string))
		d2, _ := time.Parse("2006-01-02 15:04:05", t2.(string))
		return this.gapYear(d1, d2)
	}

	if reflect.TypeOf(t1).Name() == "Time" {
		return this.gapYear(t1.(time.Time), t2.(time.Time))
	}

	if reflect.TypeOf(t1).Name() == "time.Time" {
		return this.gapYear(t1.(time.Time), t2.(time.Time))
	}

	return -1
}

// 计算日期相差多少年(注意:3到6差距是3而不是4)
func (this TimeUtil) gapYear(t1, t2 time.Time) (year int) {
	year = t1.Year() - t2.Year()

	if year < 0 {
		year = -year
	}

	return
}

// 取时间戳(秒)
func (this TimeUtil) Second() int64 {
	return time.Now().Unix()
}

// 取时间戳(纳秒)
func (this TimeUtil) NanoSecond() int64 {
	return time.Now().UnixNano()
}

// 取时间戳(毫秒)
func (this TimeUtil) MilliSecond() int64 {
	return time.Now().UnixNano() / 1e6
}
